/*
 * DIO.c
 *
 * Created: 9/04/2012 12:13:31 AM
 *  Author: Richard
 */ 

#include "DIO.h"

typedef enum
{
	DIO_nenInput = 0,
	DIO_nenOutput
} DIO_tenDataDirection;

static const struct
{
	uint8				u8Pin;
	volatile uint8*		pu8DataDirection;
	volatile uint8*		pu8PortData;
	volatile uint8*		pu8PinValue;
} DIO__rastDIORegisters[DIO_nenNumberOfPins] = 
{	
	#if 0
/* DIO_nenLED 			*/	{ PB1, &DDRB, &PORTB, &PINB },
/* DIO_nenChipSelect	*/	{ PB2, &DDRB, &PORTB, &PINB },
/* DIO_nenMOSI			*/	{ PB3, &DDRB, &PORTB, &PINB },			
/* DIO_nenMISO			*/	{ PB4, &DDRB, &PORTB, &PINB },
/* DIO_nenSCK			*/	{ PB5, &DDRB, &PORTB, &PINB },
	
/* DIO_nenV18_EN		*/	{ PC0, &DDRC, &PORTC, &PINC },
/* DIO_nenV33_EN		*/	{ PC1, &DDRC, &PORTC, &PINC },
/* DIO_nenV50_EN		*/	{ PC2, &DDRC, &PORTC, &PINC },
/* DIO_nenV_OK			*/	{ PC3, &DDRC, &PORTC, &PINC },
/* DIO_nenSDA			*/	{ PC4, &DDRC, &PORTC, &PINC },
/* DIO_nenSCL			*/	{ PC5, &DDRC, &PORTC, &PINC },
/* DIO_nenVIN_SENSE		*/	{ PC6, &DDRC, &PORTC, &PINC },
	
/* DIO_nenSD_OK			*/	{ PD0, &DDRD, &PORTD, &PIND },		
/* DIO_nenSD_EN			*/	{ PD1, &DDRD, &PORTD, &PIND },
/* DIO_nenRTC_INT		*/	{ PD2, &DDRD, &PORTD, &PIND },
/* DIO_nenVBI_OK		*/	{ PD3, &DDRD, &PORTD, &PIND },		
/* DIO_nenVBO_EN		*/	{ PD4, &DDRD, &PORTD, &PIND },
/* DIO_nenVBO_OK		*/	{ PD5, &DDRD, &PORTD, &PIND },
/* DIO_nenECLK_EN		*/	{ PD6, &DDRD, &PORTD, &PIND },
/* DIO_nenERST			*/	{ PD7, &DDRD, &PORTD, &PIND }
	#else
/* DIO_nenCurrent       */  { PA0, &DDRA, &PORTA, &PINA },
/* DIO_nenVoltage       */  { PA1, &DDRA, &PORTA, &PINA },	
/* DIO_nenLED1          */  { PA5, &DDRA, &PORTA, &PINA },
/* DIO_nenLED2          */  { PA6, &DDRA, &PORTA, &PINA },
/* DIO_nenLED3          */  { PA7, &DDRA, &PORTA, &PINA },
/* DIO_nenServo         */  { PD4, &DDRD, &PORTD, &PIND },
	#endif
};

static const struct
{
	DIO_tenDataDirection enDataDirection;
	DIO_tenLogicLevel    enOutputLevel;
} DIO__rastDIOInitConfig[DIO_nenNumberOfPins] =
{		
	#if 0
/* DIO_nenLED 			*/	{ DIO_nenOutput, tHi },
/* DIO_nenChipSelect	*/	{ DIO_nenInput,  tLo },	
/* DIO_nenMOSI			*/	{ DIO_nenInput,  tLo },
/* DIO_nenMISO			*/	{ DIO_nenOutput, tHi },
/* DIO_nenSCK			*/	{ DIO_nenInput,  tLo },
	
/* DIO_nenV18_EN		*/	{ DIO_nenOutput, tLo },
/* DIO_nenV33_EN		*/	{ DIO_nenOutput, tLo },
/* DIO_nenV50_EN		*/	{ DIO_nenOutput, tLo },
/* DIO_nenV_OK			*/	{ DIO_nenInput,  tLo },
/* DIO_nenSDA			*/	{ DIO_nenOutput, tHi },
/* DIO_nenSCL			*/	{ DIO_nenOutput, tHi },
/* DIO_nenVIN_SENSE		*/	{ DIO_nenInput,  tLo },
	
/* DIO_nenSD_OK			*/	{ DIO_nenInput,  tLo },
/* DIO_nenSD_EN			*/	{ DIO_nenOutput, tHi },
/* DIO_nenRTC_INT		*/	{ DIO_nenInput,  tLo },
/* DIO_nenVBI_OK		*/	{ DIO_nenInput,  tLo },
/* DIO_nenVBO_EN		*/	{ DIO_nenOutput, tLo },
/* DIO_nenVBO_OK		*/	{ DIO_nenInput,  tLo },
/* DIO_nenECLK_EN		*/	{ DIO_nenOutput, tLo },
/* DIO_nenERST			*/	{ DIO_nenOutput, tHi },	
	#else
/* DIO_nenCurrent       */  { DIO_nenInput,  tLo },
/* DIO_nenVoltage       */  { DIO_nenInput,  tLo },		
/* DIO_nenLED1          */  { DIO_nenOutput, tHi },
/* DIO_nenLED2          */	{ DIO_nenOutput, tHi },
/* DIO_nenLED3          */  { DIO_nenOutput, tHi },	
/* DIO_nenServo        */	{ DIO_nenOutput, tHi },	
	#endif			
};

void DIO_vInit( void )
{
	uint8 u8Index;
	
	for( u8Index = 0; u8Index < (uint8)DIO_nenNumberOfPins; u8Index++ )
	{
		/* set initial values (outputs) / pull-up enables (inputs) */
		if( DIO__rastDIOInitConfig[u8Index].enOutputLevel == tHi )
		{
			*( DIO__rastDIORegisters[u8Index].pu8PortData ) |= ( 1 << ( DIO__rastDIORegisters[u8Index].u8Pin ) );	
		}
		else
		{
			*( DIO__rastDIORegisters[u8Index].pu8PortData ) &= ~( 1 << ( DIO__rastDIORegisters[u8Index].u8Pin ) );
		}

		/* set data directions */
		if( DIO__rastDIOInitConfig[u8Index].enDataDirection == DIO_nenOutput )
		{
			*( DIO__rastDIORegisters[u8Index].pu8DataDirection ) |= ( 1 << ( DIO__rastDIORegisters[u8Index].u8Pin ) ); 
		}
		else
		{
			*( DIO__rastDIORegisters[u8Index].pu8DataDirection ) &= ~( 1 << ( DIO__rastDIORegisters[u8Index].u8Pin ) );
		}			
	}
}

void DIO_vSetOutputLevel( DIO_tenPinName enPin, DIO_tenLogicLevel enLevel )
{
	if( enLevel == tHi )
	{
		*( DIO__rastDIORegisters[enPin].pu8PortData ) |= ( 1 << ( DIO__rastDIORegisters[enPin].u8Pin ) );	
	}	
	else
	{
		*( DIO__rastDIORegisters[enPin].pu8PortData ) &= ~( 1 << ( DIO__rastDIORegisters[enPin].u8Pin ) );
	}	
}

void DIO_vToggleOutputLevel( DIO_tenPinName enPin )
{
	DIO_tenLogicLevel enCurrentLevel;
	
	enCurrentLevel = DIO_enGetInputLevel( enPin );
	enCurrentLevel ^= 1;
	DIO_vSetOutputLevel( enPin, enCurrentLevel ); 
}	

DIO_tenLogicLevel DIO_enGetInputLevel( DIO_tenPinName enPin )
{
	DIO_tenLogicLevel enReturnValue;
	
	enReturnValue = (DIO_tenLogicLevel)(*( DIO__rastDIORegisters[enPin].pu8PinValue ) & ( 1 << ( DIO__rastDIORegisters[enPin].u8Pin ) ) );
	
	return enReturnValue;
} 
